package qnb;

import javax.servlet.ServletContext;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.validation.Validator;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import qnb._common.properties.RedisConfig;
import qnb._config.LoginInterceptor;
import qnb._config.StringToDate;

/**
 * SpringMVC配置，影响不到 Servlet相关配置
 * 
 * @author Server215
 *
 */
@Configuration
@EnableWebMvc
public class SpringConfig implements WebMvcConfigurer {

	@Autowired
	private ServletContext servletContext;

	@Autowired
	private RedisConfig redisConfig;

	private static String realPath;

	/**
	 * yourPath所在项目的真实路径。注意，加上/前缀
	 * 
	 * @param yourPath
	 * @return
	 */
	public static String getRealPath(String yourPath) {
		if (null == yourPath || yourPath.isEmpty()) {
			return realPath;
		}
		return realPath + yourPath;
	}

	// 配置视图
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		realPath = servletContext.getRealPath("");
		if (realPath.endsWith("/") || realPath.endsWith("\\")) {
			realPath = realPath.substring(0, realPath.length() - 1);
		}
		System.out.println("项目真实路径:" + realPath);

//		registry.jsp();
		System.out.println("视图配置启动成功.............");
		registry.jsp("/WEB-INF/jsp/", ".jsp");
	}

	// 自定义 路径 映射
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/").setViewName("index");
		registry.addViewController("/login").setViewName("login/login");
	}

	// url->拦截器->Controller处理方法
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login/**","/static/**","/notice/get");// 排除
	}

	// 校验开关
	@Override
	public Validator getValidator() {
		return new org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean();
	}
	//请求url 绑定请求的数据类型
	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		configurer.mediaType("json", MediaType.APPLICATION_JSON_UTF8);
		configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
		configurer.mediaType("xml", MediaType.APPLICATION_XML);
	}

	/**          
	 * 配置静态资源
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		System.out.println("=============================注册资源器成功=================================");
		registry.addResourceHandler("/static/**").addResourceLocations("/public", "/static/").setCachePeriod(0);
	}
//	
	//自定义类型转换
	@Override
	public  void addFormatters(FormatterRegistry registry) {
		registry.addConverter(new StringToDate());
		/*registry.addConverter(new StringToInt());*/
	}


	/**
	 * jedis连接工厂
	 * @return
	 */
	@Bean
	public JedisConnectionFactory redisConnectionFactory() {
		RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
		config.setPassword(redisConfig.getPassword());
		config.setHostName(redisConfig.getHost());
		config.setPort(redisConfig.getPort());
		return new JedisConnectionFactory(config,jedisClientConfiguration());
	}

	/**
	 * jedis客户端配置
	 * @return
	 */
	@Bean
	public JedisClientConfiguration jedisClientConfiguration(){
		return JedisClientConfiguration.builder()
				.usePooling()//开启连接池
				.poolConfig(genericObjectPoolConfig())//连接池配置
				.build();
	}

	/**
	 * jedis连接池配置
	 * @return
	 */
	@Bean
	public GenericObjectPoolConfig genericObjectPoolConfig(){
		GenericObjectPoolConfig<Object> config = new GenericObjectPoolConfig<>();
		config.setMaxIdle(redisConfig.getMaxIdle());
		config.setMaxTotal(redisConfig.getMaxTotal());
		config.setMinIdle(redisConfig.getMinIdel());
		return config;
	}

	/**
	 * jedis template
	 * @return
	 */
	@Bean
	public  RedisTemplate<String,Object> redisTemplate(){
		RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
		Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		serializer.setObjectMapper(om);
		//序列化
		redisTemplate.setKeySerializer(serializer);
		redisTemplate.setValueSerializer(serializer);
		redisTemplate.setHashKeySerializer(serializer);
		redisTemplate.setHashValueSerializer(serializer);

//		redisTemplate.setValueSerializer(new StringRedisSerializer());
//		redisTemplate.setKeySerializer(new StringRedisSerializer());
//		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//		redisTemplate.setHashValueSerializer(new StringRedisSerializer());


		//连接工厂
		redisTemplate.setConnectionFactory(redisConnectionFactory());
		return redisTemplate;
	}

}
